#ifndef LWRB_H
#define LWRB_H

#include <stdint.h>
#include <string.h>


#ifdef __cplusplus
extern "C" {
#endif

#define LWRB_USE_MAGIC                      1

/**
 * @brief Event type for buffer operations
 */
typedef enum {
    LWRB_EVT_READ,  															/*!< Read event */
    LWRB_EVT_WRITE, 															/*!< Write event */
    LWRB_EVT_RESET, 															/*!< Reset event */
} lwrb_evt_type_t;

/**
 * @brief Buffer structure forward declaration
 */
struct lwrb;


/**
 * @brief Event callback function type
 * @param rb: Buffer handle for event
 * @param evt: Event type
 * @param bp: Number of bytes written or read (when used), depends on event type
 */
typedef void (* lwrb_evt_fn)(struct lwrb *rb, lwrb_evt_type_t evt, size_t bp);

/**
 * @brief buffer structure
 */
typedef struct lwrb
{
	unsigned char *buff;														/* !< Pointer to buffer data. */
	size_t size;																/* !< Size of buff data. */
	unsigned int read;															/* !< Next read point. */
	unsigned int write;															/* !< Next write point. */
	lwrb_evt_fn evt_fn;															/* !< Point to event callback function */
	
#if LWRB_USE_MAGIC
	uint32_t magic1;															/*!< Magic 1 word */
	uint32_t magic2;															/*!< Magic 2 word */

#endif
} lwrb_t;


unsigned char lwrb_init(lwrb_t *rb, void* buffdata, size_t size);
unsigned char lwrb_is_ready(lwrb_t *rb);
void lwrb_free(lwrb_t *rb);
void lwrb_reset(lwrb_t *rb);
void lwrb_set_evt_fn(lwrb_t *rb, lwrb_evt_fn fn);

/* Read/Write functions */
size_t lwrb_write(lwrb_t *rb, const void* data, size_t btw);
size_t lwrb_read(lwrb_t *rb, void* data, size_t btr);
size_t lwrb_peek(const lwrb_t *rb, size_t skip_count, void* data, size_t btp);

/* Buffer size information */
size_t lwrb_get_free(const lwrb_t *rb);
size_t lwrb_get_full(const lwrb_t *rb);

/* Read data block management */
void* lwrb_get_linear_block_read_address(const lwrb_t *rb);
size_t lwrb_get_linear_block_read_length(const lwrb_t *rb);
size_t lwrb_skip(lwrb_t *rb, size_t len);

/* Write data block management */
void* lwrb_get_linear_block_write_address(const lwrb_t *rb);
size_t lwrb_get_linear_block_write_length(const lwrb_t *rb);
size_t lwrb_advance(lwrb_t *rb, size_t len);


#ifdef __cplusplus
}
#endif


#endif
